<template>
  <!-- v-pagePermissions="pagePermissions"  -->
  <div class="white-bg konvajscontainer ">
    <div class="toolBox">
      <div class=" tool">
        <el-tooltip
          class="item"
          effect="dark"
          content="标注工具"
          placement="bottom"
        >
          <el-icon
            @click.stop="state.currentToolIndex = 'Rect'"
            class="llt-icon-size "
            :class="state.currentToolIndex == 'Rect' ? 'toolActive' : ''"
            ><FullScreen
          /></el-icon>
        </el-tooltip>

        <el-tooltip
          class="item"
          effect="dark"
          content="文本标记"
          placement="bottom"
        >
          <el-icon
            @click.stop="state.currentToolIndex = 'EditPen'"
            class="llt-icon-size "
            :class="state.currentToolIndex == 'EditPen' ? 'toolActive' : ''"
            ><EditPen
          /></el-icon>
        </el-tooltip>
        <el-tooltip
          class="item"
          effect="dark"
          content="删除"
          placement="bottom"
        >
          <el-icon
            @click.stop="state.currentToolIndex = 'Delete'"
            class="llt-icon-size "
            :class="state.currentToolIndex == 'Delete' ? 'toolActive' : ''"
            ><DeleteFilled
          /></el-icon>
        </el-tooltip>
        <el-tooltip
          class="item"
          effect="dark"
          content="亮度"
          placement="bottom"
        >
          <el-icon @click.stop="handleBrighten" class="llt-icon-size "
            ><Operation
          /></el-icon>
        </el-tooltip>
        <el-tooltip
          class="item"
          effect="dark"
          content="对比度"
          placement="bottom"
        >
          <el-icon @click.stop="handleContrast" class="llt-icon-size "
            ><Filter
          /></el-icon>
        </el-tooltip>
        <el-tooltip
          class="item"
          effect="dark"
          content="下载"
          placement="bottom"
        >
          <el-icon @click.stop="handleDownload" class="llt-icon-size "
            ><Download
          /></el-icon>
        </el-tooltip>
        <el-tooltip
          class="item"
          effect="dark"
          content="裁剪圈主的坐标"
          placement="bottom"
        >
          <el-icon @click.stop="handleCropDownload" class="llt-icon-size "
            ><Crop
          /></el-icon>
        </el-tooltip>
        <div></div>
        <el-button type="primary" @click="handleSaveJSON">保存</el-button>
      </div>
      <div class="w100">
        <div class="zoomBox aic jcc">
          <el-icon @click.stop="handleMinus" class="llt-icon-size "
            ><Minus
          /></el-icon>
          <el-link type="primary" style="width:100px">{{ size }}%</el-link>
          <el-icon @click.stop="handleAdd" class="llt-icon-size "
            ><Plus
          /></el-icon>
        </div>
        <div class="container" id="container"></div>
      </div>
    </div>
    <el-dialog
      v-model="dialogVisible"
      width="30%"
      title="设置亮度"
      append-to-body
    >
      <el-slider v-model="sliderValue" :min="-1" :max="1" :step="0.05" />
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="handleSaveBrighten">保存</el-button>
        </div>
      </template>
    </el-dialog>
    <el-dialog
      v-model="dialogVisibleContrast"
      width="30%"
      title="设置对比度"
      append-to-body
    >
      <el-slider
        v-model="sliderContrastValue"
        :min="-100"
        :max="100"
        :step="1"
      />
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="dialogVisibleContrast = false">取消</el-button>
          <el-button type="primary" @click="handleSaveContrast">保存</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, getCurrentInstance, onMounted, nextTick } from "vue";
import { useRouter, useRoute } from "vue-router";
import Konva from "Konva";
const internalInstance = getCurrentInstance(); //获取当前实例
// const route = internalInstance?.appContext.config.globalProperties.$route;
const router = useRouter();
const route = useRoute();

/*
基本数据类型
引用数据类型（复杂类型） 个人建议 ref初始化变量
ref 和 reactive 本质我们可以简单的理解为ref是对reactive的二次包装,
ref定义的数据访问的时候要多一个.value
*/
const dialogVisible = ref(false); //亮度
const dialogVisibleContrast = ref(false); //亮度

const sliderValue = ref(0); //亮度
const sliderContrastValue = ref(0); //对比度
const size = ref(100);
// 创建文本
// http://konvajs-doc.bluehymn.com/docs/sandbox/Editable_Text.html
const state: any = reactive({
  height: 700,
  width: 1200,
  widthImg: 0,
  heightImg: 0,
  currentToolIndex: "Rect", //默认工具 当前激活的工具类型
  stage: null, //Konva 实体类
  layerImage: null, //背景图层
  trImage: null, //图片缩放层
  stageImage: null, //图片实体类
  configKonva: {
    width: 200,
    height: 200,
  },
  configCircle: {
    x: 0,
    y: 0,
    radius: 70,
    fill: "red",
    stroke: "black",
    strokeWidth: 4,
  },
});
//设置亮度
const handleBrighten = () => {
  dialogVisible.value = true;
};

//保存亮度
const handleSaveBrighten = () => {
  state.stageImage.brightness(sliderValue.value);
  state.layerImage.batchDraw();
  dialogVisible.value = false;
};
//设置对比度
const handleContrast = () => {
  dialogVisibleContrast.value = true;
};
//保存对比度
const handleSaveContrast = () => {
  state.stageImage.contrast(sliderContrastValue.value);
  state.layerImage.batchDraw();
  dialogVisibleContrast.value = false;
};
//下载图片
const handleDownload = () => {
  var dataURL = state.stage.toDataURL({ pixelRatio: 3 });
  var link = document.createElement("a");
  link.download = "stage.png";
  link.href = dataURL;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
};
//裁剪
const handleCropDownload = () => {
  var dataURL = state.stage.toDataURL({
    pixelRatio: 1,
    x: 308,
    y: 349,
    width: 100,
    height: 100,
  });

  var link = document.createElement("a");
  link.download = "stage.png";
  link.href = dataURL;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
};
const json = {
  attrs: { width: 1200, height: 700, draggable: true },
  className: "Stage",
  children: [
    {
      attrs: {},
      className: "Layer",
      children: [
        {
          attrs: {
            id: "Image",
            filters: [null, null],
            scaleX: 0.4,
            scaleY: 0.4,
          },
          className: "Image",
        },
      ],
    },
    {
      attrs: {},
      className: "Layer",
      children: [
        { attrs: { name: "Transformer" }, className: "Transformer" },
        {
          attrs: {
            x: 154,
            y: 129,
            width: 100,
            height: 100,
            fill: "",
            stroke: "red",
            draggable: true,
            strokeWidth: 1,
            name: "Rect",
          },
          className: "Rect",
        },
      ],
    },
    {
      attrs: {},
      className: "Layer",
      children: [
        { attrs: { name: "Transformer" }, className: "Transformer" },
        {
          attrs: {
            x: 573,
            y: 175,
            width: 100,
            height: 100,
            fill: "",
            stroke: "red",
            draggable: true,
            strokeWidth: 1,
            name: "Rect",
          },
          className: "Rect",
        },
      ],
    },
  ],
};
const reloadDraw = () =>{
   for (let index = 0; index < json.children.length; index++) {
        const element = json.children[index];
        for (let index = 0; index < element.children.length; index++) {
          const shape: any = element.children[index];
          switch (shape.className) {
            case "Rect":
              createRect({
                x: shape.attrs.x,
                y: shape.attrs.y,
                width: shape.attrs.width,
                height: shape.attrs.height,
              });
              break;
            case "Image":
              size.value = shape.attrs.scaleX*100
              state.stageImage.scale({
                x: shape.attrs.scaleX,
                y: shape.attrs.scaleY,
              });
              break;
            default:
              break;
          }
        }
      }
}

/**
 * 缩小
 */
const handleMinus = () => {
  let step = 10;
  if (size.value - step <= 0) return;
  size.value = size.value - step;
  let zoom = size.value / 100;
  console.log("zoom", state.stageImage.scale);
  // state.layerImage.setScale(zoom)
  //  state.layerImage.draw()
  state.stageImage.scale({
    x: zoom,
    y: zoom,
  });
  //  state.widthImg = zoom*state.width
  //  state.heightImg = zoom*state.height
  //更新 界面
  //  console.log('state.stageImage', state.layerImage.setScale())
};
/**
 * 放大
 */
const handleAdd = () => {
  let step = 10;
  if (size.value + step >= 500) return;
  size.value = size.value + step;
  let zoom = size.value / 100;
  state.stageImage.scale({
    x: zoom,
    y: zoom,
  });
  //  state.widthImg = zoom*state.width
  //  state.heightImg = zoom*state.height
  //更新 界面
  //  console.log('state.stageImage', state.layerImage.setScale())
};
//打印当前元素位置信息
const updateText = (event: any) => {
  var lines = [
    "leftTop" + `:${event.x()},${event.y()}`,
    "RightTop: " + `:${event.x() + event.width()},${event.y()}`,
    "leftBottom: " + `:${event.x()},${event.y() + event.height()}`,
    "RightBottom: " +
      `:${event.x() + event.width()},${event.y() + event.height()}`,
    "width: " + event.width(),
    "height: " + event.height(),
    "scaleX: " + event.scaleX(),
    "scaleY: " + event.scaleY(),
  ];
};
interface CreateRect {
  x: number;
  y: number;
  width?: 100;
  height?: 100;
}
interface CreateText {
  x: number;
  y: number;
  width?: 200;
  height?: number;
  text?: "请输入";
}
//http://konvajs-doc.bluehymn.com/docs/sandbox/Image_Resize.html
const createText = (data: CreateText) => {
  const textNode: any = new Konva.Text({
    x: data.x,
    y: data.y,
    width: data.width,
    text: data.text,
    fontSize: 20,
    draggable: true,
    name: "Text",
    fill: "red",
  });

  const layer = new Konva.Layer();
  layer.add(textNode);
  state.stage.add(layer);
  var tr = new Konva.Transformer({
    node: textNode,
    name: "Transformer",
    enabledAnchors: ["middle-left", "middle-right"],
    // set minimum width of text
    boundBoxFunc: function(oldBox, newBox) {
      newBox.width = Math.max(30, newBox.width);
      return newBox;
    },
  });
  textNode.on("transform", function() {
    // reset scale, so only with is changing by transformer
    textNode.setAttrs({
      width: textNode.width() * textNode.scaleX(),
      scaleX: 1,
    });
  });
  layer.add(tr);

  layer.draw();
  layer.on("click", function(evt) {
    switch (state.currentToolIndex) {
      case "Delete":
        layer.destroy();
        break;
      default:
        break;
    }
    evt.cancelBubble = true;
  });
  textNode.on("dblclick", (evt: any) => {
    // hide text node and transformer:
    textNode.hide();
    tr.hide();
    layer.draw();

    // create textarea over canvas with absolute position
    // first we need to find position for textarea
    // how to find it?

    // at first lets find position of text node relative to the stage:
    var textPosition = textNode.absolutePosition();

    // then lets find position of stage container on the page:
    var stageBox = state.stage.container().getBoundingClientRect();

    // so position of textarea will be the sum of positions above:
    var areaPosition = {
      x: stageBox.left + textPosition.x,
      y: stageBox.top + textPosition.y,
    };

    // create textarea and style it
    var textarea: any = document.createElement("textarea");
    document.body.appendChild(textarea);

    // apply many styles to match text on canvas as close as possible
    // remember that text rendering on canvas and on the textarea can be different
    // and sometimes it is hard to make it 100% the same. But we will try...
    textarea.value = textNode.text();
    textarea.style.position = "absolute";
    textarea.style.top = areaPosition.y + "px";
    textarea.style.left = areaPosition.x + "px";
    textarea.style.width = textNode.width() - textNode.padding() * 2 + "px";
    textarea.style.height =
      textNode.height() - textNode.padding() * 2 + 5 + "px";
    textarea.style.fontSize = textNode.fontSize() + "px";
    textarea.style.border = "none";
    textarea.style.padding = "0px";
    textarea.style.margin = "0px";
    textarea.style.overflow = "hidden";
    textarea.style.background = "none";
    textarea.style.outline = "none";
    textarea.style.resize = "none";
    textarea.style.lineHeight = textNode.lineHeight();
    textarea.style.fontFamily = textNode.fontFamily();
    textarea.style.transformOrigin = "left top";
    textarea.style.textAlign = textNode.align();
    textarea.style.color = textNode.fill();
    let rotation = textNode.rotation();
    var transform = "";
    if (rotation) {
      transform += "rotateZ(" + rotation + "deg)";
    }

    var px = 0;
    // also we need to slightly move textarea on firefox
    // because it jumps a bit
    var isFirefox = navigator.userAgent.toLowerCase().indexOf("firefox") > -1;
    if (isFirefox) {
      px += 2 + Math.round(textNode.fontSize() / 20);
    }
    transform += "translateY(-" + px + "px)";

    textarea.style.transform = transform;

    // reset height
    textarea.style.height = "auto";
    // after browsers resized it we can set actual value
    textarea.style.height = textarea.scrollHeight + 3 + "px";

    textarea.focus();

    function removeTextarea() {
      textarea.parentNode.removeChild(textarea);
      window.removeEventListener("click", handleOutsideClick);
      textNode.show();
      tr.show();
      tr.forceUpdate();
      layer.draw();
    }

    function setTextareaWidth(newWidth: any) {
      if (!newWidth) {
        // set width for placeholder
        newWidth = textNode.placeholder.length * textNode.fontSize();
      }
      // some extra fixes on different browsers
      var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
      var isFirefox = navigator.userAgent.toLowerCase().indexOf("firefox") > -1;
      if (isSafari || isFirefox) {
        newWidth = Math.ceil(newWidth);
      }

      var isEdge = document.documentMode || /Edge/.test(navigator.userAgent);
      if (isEdge) {
        newWidth += 1;
      }
      textarea.style.width = newWidth + "px";
    }

    textarea.addEventListener("keydown", function(e) {
      // hide on enter
      // but don't hide on shift + enter
      if (e.keyCode === 13 && !e.shiftKey) {
        textNode.text(textarea.value);
        removeTextarea();
      }
      // on esc do not set value back to node
      if (e.keyCode === 27) {
        removeTextarea();
      }
    });

    textarea.addEventListener("keydown", function(e: any) {
      let scale = textNode.getAbsoluteScale().x;
      setTextareaWidth(textNode.width() * scale);
      textarea.style.height = "auto";
      textarea.style.height =
        textarea.scrollHeight + textNode.fontSize() + "px";
    });

    function handleOutsideClick(e: any) {
      if (e.target !== textarea) {
        textNode.text(textarea.value);
        removeTextarea();
      }
    }
    setTimeout(() => {
      window.addEventListener("click", handleOutsideClick);
    });
    evt.cancelBubble = true;
  });
};
//创建 矩形 标注区域
const createRect = (data: CreateRect) => {
  const rect1 = new Konva.Rect({
    x: data.x,
    y: data.y,
    width: data.width,
    height: data.height,
    fill: "",
    stroke: "red",
    draggable: true,
    strokeWidth: 1,
    name: "Rect",
  });
  const layer = new Konva.Layer();
  state.stage.add(layer);
  var tr1 = new Konva.Transformer({
    node: rect1,
    name: "Transformer",
    keepRatio:false,
    centeredScaling:true,
    ignoreStroke:true,
    rotationSnaps:[180, 270]
  });

  layer.add(tr1);
  layer.add(rect1);
  layer.draw();
  rect1.on("dragmove", function(data) {
    //数据导出
    // updateText(rect1);
  });
  rect1.on("transform", function() {
    // updateText(rect1);
  });
  layer.on("click", function(evt) {
    switch (state.currentToolIndex) {
      case "Delete":
        layer.destroy();
        break;
      default:
        break;
    }
    evt.cancelBubble = true;
  });
};
//初始化 容器
const InitKonva = () => {
  const konvaContainer: any = document.querySelector("#container");
  // konvaContainer.offsetWidth
  // konvaContainer.offsetHeight,
  state.stage = new Konva.Stage({
    container: "container",
    width: state.width,
    height: state.height,
    draggable: true,
  });

  // state.stage = Konva.Node.create(json, "container");
  // let Transformer = state.stage.find(".Transformer");
  const imageObj = new Image();
  imageObj.onload = function() {
    // 算出图片于画布比例
    let proportionW = state.width / imageObj.width;
    let proportionH = state.height / imageObj.height;
    state.widthImg = imageObj.width;
    state.heightImg = imageObj.height;
    //  state.stage.setHeight(imageObj.height)
    //  state.stage.setWidth(imageObj.width)

    //加载画布
    state.layerImage = new Konva.Layer();
    // darth vader
    state.stageImage = new Konva.Image({
      id: "Image",
      image: imageObj,
      x: 0,
      y: 0,
      width: state.widthImg,
      height: state.heightImg,
      draggable: false,
    });

    state.stageImage.cache();
    state.stageImage.filters([Konva.Filters.Brighten, Konva.Filters.Contrast]);
    // add cursor styling
    state.stageImage.on("mouseover", function() {
      document.body.style.cursor = "default";
    });
    state.stageImage.on("mouseout", function() {
      document.body.style.cursor = "move";
    });
    state.layerImage.add(state.stageImage);
    state.stage.add(state.layerImage);
    if (json) {
      reloadDraw()
    }

    window.onmousewheel=document.onmousewheel=(e)=>{
      console.log('e.wheelDelta', e.wheelDelta)
    if(e.wheelDelta<0){
        console.log("鼠标滚轮后滚")
    }else if(e.wheelDelta>0){
        console.log("鼠标滚轮前滚")
    }
    
}
  };
  imageObj.src = "/src/assets/001641R2MuS.jpg";
  //点击时间
  state.stage.on("click", (data: any) => {
    switch (state.currentToolIndex) {
      case "Rect":
        createRect({
          x: data.evt.offsetX,
          y: data.evt.offsetY,
          width: 100,
          height: 100,
        });
        break;
      case "EditPen":
        createText({
          x: data.evt.offsetX,
          y: data.evt.offsetY,
          text: "请输入",
          height: 100,
        });
        break;

      default:
        break;
    }
  });
};
/**
 * 保存json
 */
const handleSaveJSON = () => {
  console.log(" state.stage.toJSON()", state.stage.toJSON());
};
onMounted(() => {
  nextTick(() => {
    InitKonva();
  });
});
</script>

<style scoped lang="scss">
.konvajscontainer {
  height: 100px;
  min-height: calc(100% - 30px);
  max-height: calc(100% - 30px);
  width: 100px;
  min-width: calc(100% - 30px);
  max-width: calc(100% - 30px);
  margin: 0 15px;
  margin-top: 0;
}
.toolBox {
  display: flex;
  width: 100%;
  height: 100%;
  .tool {
    width: 140px;
    height: 100%;
    border-right: 20px solid #f0f2f5;
  }
  #container {
    width: 1200px;
    height: 700px;
    margin-left: 30px;
    box-shadow: var(--el-box-shadow-light);
  }
}
.zoomBox {
  width: 1200px;
}
</style>
